/**
 * Created with IntelliJ IDEA.
 * User: liulinhui
 * Date: 18-10-9
 * Time: 下午5:21
 * Description: ethService
 */

import {addOuterAccount, selectOuterAccountByAddress} from './datxService'
import Wallet from 'ethereumjs-wallet'
import EthUtil from 'ethereumjs-util'
import Web3 from 'web3'
import Tx from 'ethereumjs-tx'
import Mnemonic from 'bitcore-mnemonic'
import {getStorage} from "../utils/storage";
import _ from "lodash";
import crypto from "../utils/crypto";

let web3 = new Web3(new Web3.providers.HttpProvider(process.env.ETH_ENDPOINT));

/**
 * 导入以太坊账号
 * @param privateKey
 * @param secret
 */
export function addEthAccount(privateKey, secret) {
  let account = '';
  let publicKey = '';
  try {
    let privateKeyBuffer;
    if (privateKey.indexOf('0x') < 0) {
      privateKey = '0x' + privateKey;
      privateKeyBuffer = EthUtil.toBuffer(privateKey);
    }
    const wallet = Wallet.fromPrivateKey(privateKeyBuffer);
    account = web3.eth.accounts.privateKeyToAccount(privateKey);
    try {
      publicKey = wallet.getPublicKeyString();
    } catch (e) {
    }
  } catch (e) {
    return '私钥不合法';
  }
  let address = account.address;
  if (!isValidAddress(address))
    return '私钥不合法';
  return addOuterAccount('ETH', privateKey, publicKey, address, secret);
}

/**
 * 以太坊注记词
 */
export function generateSeed() {
  return new Mnemonic(Mnemonic.Words.ENGLISH).toString()
}

/**
 * 根据注记词生成私钥
 * @param code
 */
export function getPrivateKeyByCode(code) {
  code = web3.utils.sha3(code);
  let account = web3.eth.accounts.create(code);
  return account.privateKey;
}

/**
 * 判断地址合法性
 * @param address
 * @returns {*}
 */
export function isValidAddress(address) {
  return web3.utils.isAddress(address)
}

/**
 * 发送交易
 * @param from 发送者
 * @param to 接受者
 * @param secret 密码
 * @param amount 金额
 * @param cb  回调函数
 * @param gasprice 旷工费用
 * @param gasprice 自定义gaslimit
 */
export function sendTrx(from, to, secret, amount,gasprice,gaslimit,type,cb) {
  let sender = selectOuterAccountByAddress(type, from, secret);
  if (!sender)
    return cb(`${from} 账户本地不存在`);
  let privateKey = new Buffer(sender.privateKey.slice(2), 'hex');
  let txValue = web3.utils.numberToHex(web3.utils.toWei(amount+"", 'ether'));
    let price = web3.utils.numberToHex(Number(gasprice));
    let gasLimit = web3.utils.numberToHex(gaslimit);
    web3.eth.getTransactionCount(from).then(_nonce => {
      let nonce = '0x' + _nonce.toString(16);
      const rawTx = {
        from: from,
        nonce: nonce,
        gasPrice: price,
        gasLimit: gasLimit,
        to: to,
        value: txValue
      };
      // return cb(rawTx)
      let tx = new Tx(rawTx);
      tx.sign(privateKey);
      let serializedTx = tx.serialize();
        web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'))
        .on('receipt', res => {
          return cb(null, res)
        });
    })
}

/**
 * 获取地址余额
 * @param address 地址
 * @param cb 回调函数
 */
export function getBalance(address, cb) {
  web3.eth.getBalance(address)
    .then(balance => {
      cb(null, web3.utils.fromWei(balance, 'ether'))
    });
}


/**
 * ETH根据地址查询账户信息
 * @param address 地址
 * @param secret 密码
 */
export function selectOuterETH(address, secret) {
  let storage = getStorage('outer:account');
  if (!storage) return null;
  storage = JSON.parse(storage);
  let account = null;
  _(storage).forEach(obj => {
      if (address === obj.address)
        account = obj;
    }
  );
  if (account) {
    let nonce = account.privateKey.nonce;
    let encryptedMessage = account.privateKey.encryptedMessage;
    account.privateKey = crypto.decryptMessageWithSecret(encryptedMessage, nonce, secret)
  }
  return account;
}
